package com.question.business.menu.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.question.business.auth.model.dto.UserDetailDTO;
import com.question.business.menu.entity.Menu;
import com.question.business.menu.mapper.MenuMapper;
import com.question.business.menu.model.ao.*;
import com.question.business.menu.model.dto.MenuRouteDTO;
import com.question.business.menu.model.vo.*;
import com.question.business.menu.service.IMenuInterfaceService;
import com.question.business.menu.service.IMenuService;
import com.question.common.constants.SecurityConstants;
import com.question.common.constants.StringConstants;
import com.question.common.exception.BusinessException;
import com.question.common.utils.CurrentUserUtil;
import com.question.common.utils.TreeUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 菜单服务实现类
 *
 * @author star
 * @since 2023-09-11
 */
@Slf4j
@Service
@AllArgsConstructor
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    private IMenuInterfaceService interfaceService;

    private final CurrentUserUtil currentUserUtil;

    /**
     * 菜单查询
     *
     * @param ao 请求参数
     * @return List<MenuVO> 响应参数
     */
    @Override
    public List<MenuVO> queryMenuList(MenuAO ao) {
        return TreeUtil.handleTrees(baseMapper.queryMenuList(ao), MenuVO.class);
    }

    /**
     * 菜单明细查询
     *
     * @param id 菜单ID
     * @return MenuDetailVO 响应参数
     */
    @Override
    public MenuDetailVO queryMenuDetail(String id) {
        Menu entity = super.getById(id);
        if (Objects.nonNull(entity)) {
            MenuDetailVO vo = new MenuDetailVO();
            BeanUtils.copyProperties(entity, vo);
            if (StringConstants.PARENT_ID.equals(vo.getParentId())) {
                vo.setParentId(null);
            } else {
                Menu menu = baseMapper.selectById(vo.getParentId());
                vo.setParentName(Objects.nonNull(menu) ? menu.getMenuName() : null);
            }
            vo.setInterfaces(interfaceService.queryMenuInterfaceList(vo.getId()));
            return vo;
        }
        return null;
    }

    /**
     * 菜单新增数据
     *
     * @param ao 请求参数
     * @return MenuAddVO 响应参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public MenuAddVO addMenu(MenuAddAO ao) {
        Menu entity = new Menu();
        BeanUtils.copyProperties(ao, entity);
        if (StringUtils.isBlank(entity.getParentId())) {
            entity.setParentId(StringConstants.PARENT_ID);
        }
        super.save(entity);
        interfaceService.addMenuInterface(entity.getId(), ao.getInterfaces());
        MenuAddVO vo = new MenuAddVO();
        vo.setId(entity.getId());
        return vo;
    }

    /**
     * 菜单修改数据
     *
     * @param ao 数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateMenu(MenuUpdateAO ao) {
        Menu entity = new Menu();
        BeanUtils.copyProperties(ao, entity);
        if (StringUtils.isBlank(entity.getParentId())) {
            entity.setParentId(StringConstants.PARENT_ID);
        } else if (ao.getParentId().equals(entity.getId())) {
            throw new BusinessException("上级菜单不能选自己");
        }
        super.updateById(entity);
        interfaceService.addMenuInterface(entity.getId(), ao.getInterfaces());
    }

    /**
     * 菜单删除数据
     *
     * @param id 菜单ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteMenu(String id) {
        super.removeById(id);
        interfaceService.addMenuInterface(id, null);
    }

    /**
     * 菜单批量删除数据
     *
     * @param ids 请求参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchMenu(List<String> ids) {
        for (String id : ids) {
            this.deleteMenu(id);
        }
    }

    /**
     * 菜单启用、停用
     *
     * @param ao 数据
     */
    @Override
    public void enableMenu(MenuEnabledAO ao) {
        this.lambdaUpdate().eq(Menu::getId, ao.getId()).set(Menu::getEnabled, ao.getEnabled()).update(new Menu());
    }

    /**
     * 菜单下拉列表查询
     *
     * @param ao 请求参数
     * @return List<MenuDropDownVO> 响应参数
     */
    @Override
    public List<MenuDropDownVO> queryMenuDropDown(MenuDropDownAO ao) {
        return TreeUtil.handleTrees(baseMapper.queryMenuDropDown(ao), MenuDropDownVO.class);
    }

    /**
     * 根据角色ID获取菜单代码
     *
     * @param roles 角色
     * @return List<String>
     */
    @Override
    public List<String> queryMenuCodesByRoleId(List<String> roles) {
        if (CollectionUtils.isNotEmpty(roles)) {
            return baseMapper.queryMenuCodesByRoleId(roles);
        }
        return Collections.emptyList();
    }

    /**
     * 菜单栏查询
     *
     * @return List<MenuRouteVO> 响应参数
     */
    @Override
    public List<MenuRouteVO> queryMenuRoute() {
        UserDetailDTO user = currentUserUtil.getUser();
        MenuRouteDTO dto = new MenuRouteDTO();
        if (!SecurityConstants.SUPER_ADMIN.equals(user.getUsername())) {
            dto.setRoles(user.getRoles());
        }
        return TreeUtil.handleMenuTrees(baseMapper.queryMenuRoute(dto));
    }

    /**
     * 菜单最新排序
     *
     * @param parentId 请求参数
     * @return Integer 响应参数
     */
    @Override
    public Integer createMenuOrder(String parentId) {
        return baseMapper.selectMaxOrderByParentId(parentId);
    }

}